'''
@Description: In User Settings Edit
@Author: your name
@Date: 2019-08-02 22:48:24
@LastEditTime: 2019-11-08 18:47:43
@LastEditors: Please set LastEditors
'''

from ...pao_python.pao.commom import get_data, find_collection
from ...pao_python.pao.data import get_cur_time, get_date, date_to_string, DataProcess, dataframe_to_list, process_db
from ...service.buss_iec.competence_assessment import CompetenceAssessmentService
from ...service.buss_mis.service_operation import ServiceOperationService
from ...service.common import get_info, SerialNumberType, get_serial_number, execute_python, get_area_id
from ...service.buss_pub.bill_manage import OperationType, TypeId, as_date
from ...service.buss_pub.personnel_organizational import User
from ...service.mongo_bill_service import MongoBillFilter
from ...pao_python.pao.service.data.mongo_db import MongoService, MongoFilter, C, N, F, as_date
from ...service.buss_pub.bill_manage import BillManageService, OperationType, TypeId, Status
from ...service.buss_pub.personnel_organizational import UserCategory, UserType
from ...service.app.service_detail import ServiceProductDetailService
import datetime
import collections
from .accommodation_process import CheckInStatus
from ...pao_python.pao.remote import JsonRpc2Error
from ...service.common import get_current_user_id, get_current_role_id, get_current_organization_id, get_string_time, get_str_to_age
from ...service.buss_mis.financial_account import FinancialAccountObject
from ...service.constant import AccountType, PayType, PayStatue, AccountStatus, plat_id
from ...models.financial_manage import FinancialAccount


class CheckInService(MongoService):

    def __init__(self, db_addr, db_port, db_name, db_user, db_pwd, inital_password, session):
        DataProcess.__init__(self, db_addr, db_port, db_name, db_user, db_pwd)
        self.inital_password = inital_password
        self.session = session
        self.bill_manage_service = BillManageService(
            db_addr, db_port, db_name, db_user, db_pwd, inital_password, session)
        self.service_product_detail_service = ServiceProductDetailService(
            self.db_addr, self.db_port, self.db_name, self.db_user, self.db_pwd, self.inital_password, self.session)

    def get_check_in_list(self, org_list, condition, page, count):
        if 'create_date' in condition.keys():
            condition['end_date'] = as_date(
                condition['create_date']) + datetime.timedelta(days=1)
        keys = ['id', 'name', 'bed_number',
                'bed_name', 'create_date', 'user_id', 'end_date', 'user_number']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.match_bill(
            (C('id') == values['id'])
            & (C('user_id') == values['user_id'])
            & (as_date(values['create_date']) < C('create_date'))
            & (values['end_date'] > C('create_date'))
            & (C('state') == CheckInStatus.check_in.value)
            & (C('organization_id').inner(org_list)))\
            .inner_join_bill('PT_User', 'user_id', 'id', 'user')\
            .match_bill(
                (C('user.name').like(values['name']))
                & (C('user.id_card').like(values['user_number']))
        )\
            .inner_join_bill('PT_Bed', 'user_id', 'residents_id', 'bed')\
            .match_bill(C('bed.name').like(values['bed_name']))\
            .inner_join_bill('PT_Service_Order', 'order_id', 'id', 'order')\
            .lookup_bill('PT_Behavioral_Competence_Assessment_Record', 'user_id', 'elder', 'recode')\
            .add_fields({
                'bed_number': '$bed.bed_code',
                'bed_name': '$bed.name',
                'bed_id': '$bed.id',
                'name': '$user.name',
                'family_name': '$user.personnel_info.family_name',
                'sex': '$user.personnel_info.sex',
                'personnel_category': '$user.personnel_info.personnel_category',
                'id_card': '$user.id_card',
                'recode': self.ao.slices('$recode', 1, -1),
                'age': '$user.personnel_info.age'
                # 'personnel_info': '$user.personnel_info'
            })\
            .add_fields({'nursing_level': '$recode.nursing_level'})\
            .match_bill(
            (C('id') == values['id'])
            & (C('user.name').like(values['name']))
            & (C('user_id') == values['user_id'])
            & (C('bed_number').like(values['bed_number']))
            & (C('bed_name').like(values['bed_name']))
            & (as_date(values['create_date']) < C('create_date'))
            & (values['end_date'] > C('create_date'))
            & (C('state') == CheckInStatus.check_in.value)
            & (C('organization_id').inner(org_list)))\
            .sort({'create_date': -1})\
            .project({'_id': 0, 'user._id': 0, 'bed._id': 0, 'order._id': 0, 'recode._id': 0})
        res = self.page_query(_filter, 'IEC_Check_In', page, count)
        for i, x in enumerate(res['result']):
            data = res['result'][i]['user']['personnel_info']['date_birth']
            date_res = get_string_time(data, '%Y-%m-%d')
            res['result'][i]['user']['personnel_info']['date_birth'] = date_res
            res['result'][i]['user']['personnel_info']['age'] = get_str_to_age(
                date_res)
        return res

    def add_check_in(self, elder_info, evaluation_info, service_item):
        # 当前时间
        now = get_cur_time()
        _filter = MongoBillFilter()
        keys = ['id_card', 'personnel_category']
        values = self.get_value(elder_info, keys)
        _filter.match_bill((C('personnel_info.personnel_category') == values['personnel_category']) & (C('id_card')) == values['id_card'])\
               .project({'_id': 0})
        res = self.page_query(_filter, 'PT_User', None, None)
        elder_info['personnel_category'] = UserCategory.Elder
        _filter_user = MongoBillFilter()
        # 组装长者表数据结构
        elder = {
            'personnel_info': elder_info,
            'personnel_type': UserType.Personnel,
            'name': elder_info['name'],
            'id_card': elder_info['id_card'],
            'id_card_type': '身份证',
            'admin_area_id': get_area_id(self, _filter_user)
        }
        # 判断是否已存在该长者
        if len(res['result']):
            elder['id'] = res['result'][0]['id']
            _filter_user = MongoBillFilter()
            _filter_user.match_bill((C('user_id') == elder['id']) & (
                C('state') == CheckInStatus.check_in.value))
            user_res = self.query(_filter_user, 'IEC_Check_In')
            if len(user_res):
                raise JsonRpc2Error('-36010', '当前长者已入住')
            self.bill_manage_service.add_bill(
                OperationType.update.value, TypeId.checkIn.value, elder, 'PT_User')
        else:
            elder = get_info(elder, self.session)
            self.bill_manage_service.add_bill(
                OperationType.add.value, TypeId.checkIn.value, elder, 'PT_User')
        # 补充长者更新信息
        # 为评估记录信息添加长者id
        evaluation_info['elder'] = elder['id']
        CompetenceAssessmentService(self.db_addr, self.db_port, self.db_name, self.db_user, self.db_pwd,
                                    self.inital_password, self.session).update_competence_assessment(evaluation_info)
        # 为服务订单添加长者id
        order_code = ''

        def process_func(db):
            nonlocal order_code
            order_code = get_serial_number(db, SerialNumberType.order.value)
        process_db(self.db_addr, self.db_port, self.db_name,
                   process_func, self.db_user, self.db_pwd)
        order_recode = {
            'purchaser_id': elder['id'],
            'order_code': order_code,
            'service_provider_id': service_item['service_provider_id'] if 'service_provider_id' in service_item else get_current_organization_id(self.session),
            'status': '未服务',
            'order_date': now,
            'service_date': now,
            'detail': service_item['details'],
            'is_paying_first': '0'
        }
        # 生成订单
        order_recode = get_info(order_recode, self.session)
        # 住宿记录
        accommondation_recode = {
            'residents_id': elder['id'], 'checkin_date': get_cur_time(), 'status': '入住', 'bed_id': service_item.get('bed_id')}
        accommondation_recode = get_info(accommondation_recode, self.session)

        # 绑定床位
        bed_info = {
            'id': service_item.get('bed_id'),
            'residents_id': elder.get('id')
        }
        # 新增入住记录
        check_in_recode = get_info({
            'user_id': elder['id'], 'accommodation_id': accommondation_recode['id'], 'order_id': order_recode['id'], 'state': '居住中'}, self.session)

        # 新增账户信息（1个机构储蓄、1个app储蓄、1个真实账户、1个补贴账户）
        # 机构储蓄对象
        org_id = get_current_organization_id(self.session)
        org_account_data = FinancialAccountObject(
            AccountType.account_recharg_wel, elder['id'], org_id, AccountStatus.normal, 1, AccountType.account_recharg_wel, {}, 0)
        org_account = get_info(org_account_data.to_dict(), self.session)
        # app储蓄对象
        app_account_data = FinancialAccountObject(
            AccountType.account_recharg_app, elder['id'], plat_id, AccountStatus.normal, 2, AccountType.account_recharg_app, {}, 0)
        app_account = get_info(app_account_data.to_dict(), self.session)
        # 真实账户对象
        real_account_data = FinancialAccountObject(
            AccountType.account_real, elder['id'], None, AccountStatus.normal, 3, AccountType.account_real, {}, 0)
        real_account = get_info(real_account_data.to_dict(), self.session)
        # 补贴账户对象
        subsidy_account_data = FinancialAccountObject(
            AccountType.account_subsidy, elder['id'], None, AccountStatus.normal, 4, AccountType.account_subsidy, {}, 0)
        subsidy_account = get_info(
            subsidy_account_data.to_dict(), self.session)
        # 最终一起增加到数据库中
        self.bill_manage_service.add_bill(OperationType.update.value,
                                          TypeId.checkIn.value, [bed_info], ['PT_Bed'])
        self.bill_manage_service.add_bill(OperationType.add.value,
                                          TypeId.checkIn.value, [[order_recode], [accommondation_recode], [check_in_recode], [org_account, app_account, real_account, subsidy_account]], ['PT_Service_Order', 'PT_Accommodation_Record', 'IEC_Check_In', FinancialAccount().name])
        return {'create_date': now}

    def get_all_product(self, condition):
        keys = ['id']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.match_bill((C('id') == values['id']))\
            .lookup_bill('PT_User', 'org_id', 'id', 'org_info')\
            .unwind('org_info')\
            .unwind('org_info.qualification_info')\
            .lookup_bill('PT_Qualification_Type', 'org_info.qualification_info.qualification_type_id', 'id', 'qualification_type_info')\
            .lookup_bill('PT_Service_Order', 'id', 'detail.product_id', 'order_info')\
            .match((C('qualification_type_info.name').like('服务评级')))\
            .add_fields({'org_name': '$org_info.name',
                         'org_address': '$org_info.address',
                         'pay_count': self.ao.size('$order_info'),
                         'org_level': '$org_info.qualification_info.qualification_level'})\
            .project({'_id': 0, 'org_info._id': 0, 'qualification_type_info._id': 0, 'order_info._id': 0})
        res = self.query(_filter, 'PT_Service_Product')
        porduct_item_list = []
        try:
            if res:
                product_queue = collections.deque()
                product_queue.append(res[0])
                while len(product_queue) != 0:
                    res_f = product_queue.popleft()
                    if res_f.get('product_collection'):
                        for product_id_list in res_f.get('product_collection'):
                            res_child = self.service_product_detail_service.get_children_tree(
                                product_id_list.get("product_id"))
                            if res_child:
                                if res_child[0].get('product_collection'):
                                    product_queue.append(res_child[0])
                                else:
                                    porduct_item_list.append(res_child[0])
                    else:
                        porduct_item_list.append(res_f)
                for product_item in porduct_item_list:
                    product_item_price = 0
                    if product_item.get('valuation_formula') and product_item.get('option_list'):
                        product_item_price = execute_python(product_item.get(
                            'valuation_formula'), product_item.get('option_list'), 'option_name', 'option_value')
                        product_item['valuation_amount'] = product_item_price
        except Exception as e:
            print(e)
        return porduct_item_list

    def create_product_order(self, pro_id, count):
        '''获取订单detail'''
        try:
            product_list = self.get_all_product({'id': pro_id})
            new_product_list = []
            if product_list:
                for product in product_list:
                    pro_dict = {}
                    pro_dict['product_id'] = product.get('id')
                    pro_dict['product_name'] = product.get('name')
                    pro_dict['valuation_formula'] = product.get(
                        'valuation_formula')
                    pro_dict['option_list'] = product.get('option_list')
                    pro_dict['contract_terms'] = product.get(
                        'additonal_contract_terms')
                    pro_dict['remark'] = product.get('remark')
                    pro_dict['count'] = count
                    new_product_list.append(pro_dict)
            return new_product_list
        except Exception as e:
            print(e)

    def update_check_in(self, service_item):
        # 绑定床位
        bed_info = {
            'id': service_item['bed_id'],
            'residents_id': service_item['residents_id']
        }
        self.bill_manage_service.add_bill(
            OperationType.update.value, TypeId.checkIn.value, bed_info, 'PT_Bed')
        # 更新订单记录
        order_recode = {
            'purchaser_id': service_item['residents_id'],
            'service_provider_id': service_item['service_provider_id'],
            'service_item': service_item['service_item']
        }
        order_recode = get_info(order_recode, self.session)
        self.bill_manage_service.add_bill(
            OperationType.update.value, TypeId.checkIn.value, order_recode, 'PT_Service_Order')
        # 新增入住记录
        # check_in_recode = {'user_id':elder['id'],'accommodation_id':accommondation_recode['id'],'order_id':order_recode['id']}
        # self._add_update_and_bill(check_in_recode, 'IEC_Check_In')
        # self.res = {'create_date':get_date()}

    def add_check_in_special(self, service_item):
        now = get_cur_time()
        user_id = service_item['user_id']
        _filter_user = MongoBillFilter()
        _filter_user.match_bill((C('user_id') == user_id) & (
            C('state') == CheckInStatus.check_in.value))
        user_res = self.query(_filter_user, 'IEC_Check_In')
        if len(user_res):
            raise JsonRpc2Error('-36010', '当前长者已入住')
        # 为服务订单添加长者id
        order_code = ''

        def process_func(db):
            nonlocal order_code
            order_code = get_serial_number(db, SerialNumberType.order.value)
        process_db(self.db_addr, self.db_port, self.db_name,
                   process_func, self.db_user, self.db_pwd)
        order_recode = {
            'purchaser_id': user_id,
            'order_code': order_code,
            'service_provider_id': service_item['service_provider_id'] if 'service_provider_id' in service_item else get_current_organization_id(self.session),
            'status': '未服务',
            'order_date': now,
            'service_date': now,
            'detail': service_item['details'],
            'is_paying_first': '0'
        }
        # 生成订单
        order_recode = get_info(order_recode, self.session)
        # 住宿记录
        accommondation_recode = {
            'residents_id': user_id, 'checkin_date': get_cur_time(), 'status': '入住', 'bed_id': service_item.get('bed_id')}
        accommondation_recode = get_info(accommondation_recode, self.session)

        # 绑定床位
        bed_info = {
            'id': service_item.get('bed_id'),
            'residents_id': user_id
        }
        # 新增入住记录
        check_in_recode = get_info({
            'user_id': user_id, 'accommodation_id': accommondation_recode['id'], 'order_id': order_recode['id'], 'state': '居住中'}, self.session)

        # 新增账户信息（1个机构储蓄、1个app储蓄、1个真实账户、1个补贴账户）
        # 机构储蓄对象
        org_id = get_current_organization_id(self.session)
        org_account_data = FinancialAccountObject(
            AccountType.account_recharg_wel, user_id, org_id, AccountStatus.normal, 1, AccountType.account_recharg_wel, {}, 0)
        org_account = get_info(org_account_data.to_dict(), self.session)
        # app储蓄对象
        app_account_data = FinancialAccountObject(
            AccountType.account_recharg_app, user_id, plat_id, AccountStatus.normal, 2, AccountType.account_recharg_app, {}, 0)
        app_account = get_info(app_account_data.to_dict(), self.session)
        # 真实账户对象
        real_account_data = FinancialAccountObject(
            AccountType.account_real, user_id, None, AccountStatus.normal, 3, AccountType.account_real, {}, 0)
        real_account = get_info(real_account_data.to_dict(), self.session)
        # 补贴账户对象
        subsidy_account_data = FinancialAccountObject(
            AccountType.account_subsidy, user_id, None, AccountStatus.normal, 4, AccountType.account_subsidy, {}, 0)
        subsidy_account = get_info(
            subsidy_account_data.to_dict(), self.session)
        # 最终一起增加到数据库中
        self.bill_manage_service.add_bill(OperationType.update.value,
                                          TypeId.checkIn.value, [bed_info], ['PT_Bed'])
        self.bill_manage_service.add_bill(OperationType.add.value,
                                          TypeId.checkIn.value, [[order_recode], [accommondation_recode], [check_in_recode], [org_account, app_account, real_account, subsidy_account]], ['PT_Service_Order', 'PT_Accommodation_Record', 'IEC_Check_In', FinancialAccount().name])
        return {'create_date': now}
